﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using eCompany;
using eCompany.eObj;

namespace eCompany.eManager
{
    public class eManager
    {
        #region currency definition
        public static string[] m_currency_code_list = {"GLD",
            "ARS",
            "ATS",
            "AUD",
            "BAM",
            "BEF",
            "BGN",
            "BOB",
            "BRL",
            "BYR",
            "CAD",
            "CHF",
            "CLP",
            "CNY",
            "COP",
            "CYP",
            "CZK",
            "DEM",
            "DKK",
            "EEK",
            "ESP",
            "FIM",
            "FRF",
            "GBP",
            "GRD",
            "HRK",
            "HUF",
            "IDR",
            "IEP",
            "INR",
            "IRR",
            "ITL",
            "JPY",
            "KPW",
            "KRW",
            "LTL",
            "LVL",
            "MDL",
            "MEP",
            "MKD",
            "MXN",
            "MYR",
            "NIS",
            "NLG",
            "NOK",
            "NZD",
            "PEN",
            "PHP",
            "PKR",
            "PLN",
            "PTE",
            "PYG",
            "RON",
            "RSD",
            "RUB",
            "SEK",
            "SGD",
            "SIT",
            "SKK",
            "THB",
            "TRY",
            "TWD",
            "UAH",
            "USD",
            "UYU",
            "VEB",
            "ZAR"};
        #endregion

        #region Tools
        public static string formatDouble(double value)
        {
            return formatDouble(value, 2);
        }
        public static string formatDouble(double value, int dec)
        {
            return value.ToString("F" + dec.ToString());
        }
        #endregion

        #region File Management
        public void loadFile(string filename, ref organisation ret_org)
        {
            try
            {
                XmlSerializer ser = new XmlSerializer(typeof(organisation));
                TextReader t = new StreamReader(filename);
                organisation c = (organisation)ser.Deserialize(t);
                t.Close();
                ret_org = c;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void loadFile(string filename, ref currency_list ret_cl)
        {
            try
            {
                XmlSerializer ser = new XmlSerializer(typeof(currency_list));
                TextReader t = new StreamReader(filename);
                currency_list c = (currency_list)ser.Deserialize(t);
                t.Close();
                ret_cl = c;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void saveFile(string filename, organisation org)
        {
            XmlSerializer ser = new XmlSerializer(typeof(organisation));
            TextWriter t = new StreamWriter(filename);
            ser.Serialize(t, org);
            t.Close();
        }
        public void saveFile(string filename, currency_list cl)
        {
            XmlSerializer ser = new XmlSerializer(typeof(currency_list));
            TextWriter t = new StreamWriter(filename);
            ser.Serialize(t, cl);
            t.Close();
        }
        #endregion

        #region Company Management
        public company addCompany(organisation org, 
                                string company_name, 
                                company_type_enum company_type, 
                                string default_currency, 
                                double base_value, 
                                double base_gld_value, 
                                double base_stock_value,
                                double base_material_value)
        {
            company c = new company();
            c.id = Guid.NewGuid().ToString();
            c.name = company_name;
            c.type = company_type;
            c.production_ratio = eCompany.eRules.eCompanyRules.getProductModifier(company_type);

            addAccount(c, "GLD", base_gld_value);
            account acc = addAccount(c, default_currency, base_value);
            c.default_account = acc.id;

            stock s = new stock();
            s.date = DateTime.Now;
            s.production_cost = 0;
            s.volume_in = base_stock_value;
            c.company_stock.Add(s);

            material_stock ms = new material_stock();
            ms.material_type = eCompany.eRules.eCompanyRules.getCompanyRawType(company_type);
            material m = new material();
            m.date = DateTime.Now;
            m.id = Guid.NewGuid().ToString();
            m.volume_in = base_material_value;
            ms.materials.Add(m);

            c.material_list.Add(ms);

            org.company_list.Add(c);

            return c;
        }
        public company getCompany(organisation org, Guid company_id)
        {
            foreach (company c in org.company_list)
            {
                if (c.id == company_id.ToString())
                    return c;
            }
            return null;
        }
        public company getCompany(organisation org, string company_name)
        {
            foreach (company c in org.company_list)
            {
                if (c.name == company_name)
                    return c;
            }
            return null;
        }
        public material_stock getMaterialStock(company c, material_type_enum rawType)
        {
            foreach (material_stock ms in c.material_list)
            {
                if (ms.material_type == rawType)
                    return ms;
            }
            return null;
        }
        public void buyMaterials(company c, material_type_enum material_type, double volume, double unit_price)
        {
            DateTime dt = DateTime.Now;

            foreach (material_stock ms in c.material_list)
            {
                if (ms.material_type == material_type)
                {
                    Guid trans_guid = Guid.NewGuid();
                    Guid mat_guid = Guid.NewGuid();

                    account acc = getAccount(c, Guid.Parse(c.default_account));
                    transaction t = new transaction();
                    t.Date = dt;
                    t.id = trans_guid.ToString();
                    t.Type = transaction_type.Material;
                    t.Value = -unit_price * volume;
                    t.info = mat_guid.ToString();

                    acc.transaction_list.Add(t);

                    material m = new material();
                    m.id = mat_guid.ToString();
                    m.unit_price = unit_price;
                    m.volume_in = volume;
                    m.date = dt;
                    m.transaction_id = trans_guid.ToString();

                    ms.materials.Add(m);

                    return;
                }
            }
        }
        public double useMaterials(company c, material_type_enum material_type, double volume)
        {
            double vol = volume;
            double mat_cost = 0;

            DateTime dt = DateTime.Now;

            foreach (material_stock ms in c.material_list)
            {
                if (ms.material_type == material_type)
                {
                    var q =
                        from material m in ms.materials
                        where m.volume_out < m.volume_in
                        orderby m.date ascending
                        select m;

                    foreach (material m in q)
                    {
                        if (m.volume_in - m.volume_out >= vol)
                        {
                            m.volume_out = m.volume_out + vol;
                            mat_cost = vol * m.unit_price;
                            return mat_cost;
                        }
                        else
                        {
                            vol -= m.volume_in - m.volume_out;
                            m.volume_out = m.volume_in;
                            mat_cost += vol * m.unit_price;
                        }
                    }
                }
            }
            return mat_cost;
        }
        public double getMaterialCount(company c, material_type_enum material_type)
        {
            foreach (material_stock ms in c.material_list)
            {
                if (ms.material_type == material_type)
                {
                    double count = 0;
                    foreach (material m in ms.materials)
                        count += (m.volume_in-m.volume_out);

                    return count;
                }
            }
            return -1;
        }
        public double getMaterialValue(company c, material_type_enum material_type)
        {
            foreach (material_stock ms in c.material_list)
            {
                if (ms.material_type == material_type)
                {
                    double val = 0;
                    foreach (material m in ms.materials)
                            val += ((double)m.volume_in-m.volume_out)*m.unit_price;
                    return val;
                }
            }
            return -1;
        }
        #endregion

        #region Company Stock Management
        public void addStock(company c, employee e, DateTime dt,double volume, double product_cost)
        {
            stock s = new stock();
            s.employee = e.id;
            s.date = dt;
            s.production_cost = product_cost;
            s.volume_in = volume;
            s.volume_out = 0;
            c.company_stock.Add(s);
        }
        public void useStock(company c, double volume)
        {
            double vol = volume;

            var q =
                from stock s in c.company_stock
                where s.volume_out<s.volume_in
                orderby s.date ascending
                select s;

            foreach (stock s in q)
            {
                if (s.volume_in - s.volume_out >= vol)
                {
                    s.volume_out = s.volume_out + vol;
                    return;
                }
                else
                {
                    vol -= s.volume_in - s.volume_out;
                    s.volume_out = s.volume_in;
                }
            }
        }
        public double getStockCount(company c)
        {
            double count = 0;
            foreach (stock s in c.company_stock)
                count += s.volume_in - s.volume_out;

            return count;
        }
        public double getStockValue(company c)
        {
            double val = 0;
            foreach (stock s in c.company_stock)
            {
                    val += (s.volume_in-s.volume_out) * (double)s.production_cost;
            }
            return val;
        }
        public stock getStock(company c, employee e, DateTime d)
        {
            var q =
                from stock s in c.company_stock
                where s.employee == e.id && s.date.Date == d.Date
                select s;

            if (q.Count<stock>() == 0)
                return null;
            return q.First<stock>();
        }
        #endregion

        #region Employee Management
        public void addEmployee(company comp, string name, double salary)
        {
            DateTime dt = DateTime.Now;

            employee e = new employee();
            e.id = Guid.NewGuid().ToString();
            e.date_in = dt;
            e.name = name;

            salary s = new salary();
            s.date = dt;
            s.value = salary / 8;

            e.salary_list.Add(s);
            comp.employee_list.Add(e);
        }

        public employee getEmployee(company comp, Guid employee_id)
        {
            foreach (employee e in comp.employee_list)
            {
                if (e.id == employee_id.ToString() && e.deleted == false)
                    return e;
            }
            return null;
        }
        public employee getEmployee(company comp, string employee_name)
        {
            foreach (employee e in comp.employee_list)
            {
                if (e.name == employee_name && e.deleted == false)
                    return e;
            }
            return null;
        }
        public employee getEmployeeByApiId(company comp, string emp_api_id, bool bIn)
        {
            var q =
                from employee e in comp.employee_list
                where ((bIn == true && e.date_out == null) || (bIn == false)) && e.api_id == emp_api_id && e.deleted == false
                orderby e.date_in descending, e.date_out ascending
                select e;

            if (q.Count<employee>() == 0)
                return null;
            return q.First<employee>();
            /*foreach (employee e in comp.employee_list)
            {
                if (e.api_id != null && e.api_id == emp_api_id)
                    if((bIn == true && e.date_out == null) || (bIn == false))
                        return e;
            }
            return null;*/
        }
        public employee getEmployee(organisation org, Guid employee_id)
        {
            foreach (company c in org.company_list)
            {
                foreach (employee e in c.employee_list)
                {
                    if (e.id == employee_id.ToString() && e.deleted == false)
                        return e;
                }
            }
            return null;
        }
        public employee getEmployee(organisation org, string employee_name)
        {
            foreach (company c in org.company_list)
            {
                foreach (employee e in c.employee_list)
                {
                    if (e.name == employee_name && e.deleted == false)
                        return e;
                }
            }
            return null;
        }

        public void setEmployeeSalary(employee e, double dsal)
        {
            salary s = new salary();
            s.date = DateTime.Now;
            s.value = dsal;
            e.salary_list.Add(s);
        }
        public double getEmployeeSalary(employee e)
        {
            var q =
                from salary s in e.salary_list
                orderby s.date descending
                select s;

            if(q.Count<salary>()>0)
                return q.First<salary>().value;
            return 0;
        }
        public work getEmployeeLastWork(company c, employee e)
        {
            DateTime dt = DateTime.MinValue;

            var q =
                from work w in c.work_list
                where w.employee == e.id
                orderby w.date descending
                select w;

            if(q.Count<work>()>0)
                return q.First<work>();
            return null;
        }
        public void workEmployee(company c, employee e, DateTime dt, int hours, int productivity/*, int material*/)
        {
            double product_created = eCompany.eRules.eCompanyRules.getWorkProducedUnit(c, e, productivity);
            int mat_count = (int)product_created * eCompany.eRules.eCompanyRules.getMaterialUse(c.type, c.customized_point);

            double sal = getEmployeeSalary(e);
            work w = new work();
            w.date = dt;
            w.employee = e.id;
            w.hours = hours;
            w.material_used = mat_count;
            w.productivity = productivity;
            w.salary = sal;
            //w.product_created = productivity/c.production_ratio/80;
            w.product_created = product_created;
            c.work_list.Add(w);

            double mat_cost = 0;
            if(!eCompany.eRules.eCompanyRules.isMaterialCompanyType(c.type))
                mat_cost = useMaterials(c, eCompany.eRules.eCompanyRules.getCompanyRawType(c.type), mat_count);

            addStock(c, e, dt, w.product_created, (sal*hours) / w.product_created+mat_cost/w.product_created);

            account acc = getAccount(c, Guid.Parse(c.default_account));
            transaction t = new transaction();
            t.Date = dt;
            t.id = Guid.NewGuid().ToString();
            t.Type = transaction_type.Salary;
            t.Value = -sal*hours;
            t.info = e.id;
            acc.transaction_list.Add(t);
        }
        public double getEmployeeProductivity(company c, employee e, DateTime dt)
        {
            DateTime dt1 = new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0);
            DateTime dt2 = new DateTime(dt.Year, dt.Month, dt.Day);
            dt2 = dt2.AddDays(1);
            dt2 = dt2.AddTicks(-1);
            var q =
                from work w in c.work_list
                where w.date>= dt1 && w.date <= dt2 && w.employee == e.id
                select w.productivity;

            return q.Sum();
        }
        public double getEmployeeProduct(company c, employee e, DateTime dt)
        {
            DateTime dt1 = new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0);
            DateTime dt2 = new DateTime(dt.Year, dt.Month, dt.Day);
            dt2 = dt2.AddDays(1);
            dt2 = dt2.AddTicks(-1);
            var q =
                from work w in c.work_list
                where w.date >= dt1 && w.date <= dt2 && w.employee == e.id
                select w.product_created;

            return q.Sum();
        }
        #endregion

        #region Account Management
        public void adjustAccount(company comp, string cur, double new_value)
        {
            account acc = getAccount(comp, cur);
            adjustAccount(acc, new_value);
        }
        public void adjustAccount(account acc, double new_value)
        {
            double current_value = getAccountValue(acc);

            transaction t = new transaction();
            t.Date = DateTime.Now;
            t.id = Guid.NewGuid().ToString();
            t.Type = transaction_type.Adjust;
            t.Value = new_value - current_value;
            acc.transaction_list.Add(t);
        }
        public account addAccount(company comp, string cur, double base_value)
        {
            account acc = new account();
            acc.id = Guid.NewGuid().ToString();
            acc.name = "Account "+cur;
            acc.currency = cur;

            transaction t = new transaction();
            t.Date = DateTime.Now;
            t.id = Guid.NewGuid().ToString();
            t.Type = transaction_type.Adjust;
            t.Value = base_value;
            acc.transaction_list.Add(t);

            comp.account_list.Add(acc);

            return acc;
        }
        public account addAccount(organisation org, string cur, double base_value)
        {
            account acc = new account();
            acc.id = Guid.NewGuid().ToString();
            acc.name = "Account " + cur;
            acc.currency = cur;

            transaction t = new transaction();
            t.Date = DateTime.Now;
            t.id = Guid.NewGuid().ToString();
            t.Type = transaction_type.Adjust;
            t.Value = base_value;
            acc.transaction_list.Add(t);

            org.account_list.Add(acc);

            return acc;
        }
        public account getAccount(company comp, Guid account_id)
        {
            foreach (account acc in comp.account_list)
            {
                if (acc.id == account_id.ToString())
                    return acc;
            }
            return null;
        }
        public account getAccount(company comp, string curr)
        {
            foreach (account acc in comp.account_list)
            {
                if (acc.currency == curr)
                    return acc;
            }
            return null;
        }
        public account getAccount(organisation org, Guid account_id)
        {
            foreach (account acc in org.account_list)
            {
                if (acc.id == account_id.ToString())
                    return acc;
            }
            return null;
        }
        public account getAccount(organisation org, string curr)
        {
            foreach (account acc in org.account_list)
            {
                if (acc.currency == curr)
                    return acc;
            }
            return null;
        }

        public void addTransaction(company comp, string curr, transaction t)
        {
            foreach (account acc in comp.account_list)
            {
                if (acc.currency == curr)
                {
                    acc.transaction_list.Add(t);
                    return;
                }
            }
        }
        public double getAccountValue(account acc)
        {
            double val = 0;
            foreach (transaction t in acc.transaction_list)
            {
                val += t.Value;
            }
            return val;
        }
        public double getAccountValue(account acc, DateTime dt)
        {
            DateTime dt2 = new DateTime(dt.Year, dt.Month, dt.Day);
            dt2 = dt2.AddDays(1);
            dt2 = dt2.AddTicks(-1);
            var q =
                from transaction t in acc.transaction_list
                where t.Date<=dt2
                select t.Value;
            return q.Sum();
        }
        public double getAccountValue(account acc, DateTime dt_deb, DateTime dt_fin)
        {
            var q =
                from transaction t in acc.transaction_list
                where t.Date >= dt_deb && t.Date <=dt_fin
                select t.Value;
            return q.Sum();
        }
        public double getAccountSellVolumeValue(account acc, DateTime dt_deb, DateTime dt_fin)
        {
            var q =
                from transaction t in acc.transaction_list
                where t.Date.Date >= dt_deb.Date && t.Date.Date <= dt_fin.Date && t.Type == transaction_type.Sell && t.Volume != null
                select (double)t.Volume;
            return q.Sum();
        }
        public double getAccountSellValue(account acc, DateTime dt_deb, DateTime dt_fin)
        {
            var q =
                from transaction t in acc.transaction_list
                where t.Date.Date >= dt_deb.Date && t.Date.Date <= dt_fin.Date && t.Type == transaction_type.Sell
                select (double)t.Value;
            return q.Sum();
        }
        #endregion

        #region Shop Management
        public shop addShop(company comp, string cur, double base_shop_stock)
        {
            shop s = new shop();
            s.currency = cur;
            if (base_shop_stock > 0)
            {
                shop_stock st = new shop_stock();
                st.date = DateTime.Now;
                st.production_cost = 0;
                st.volume_in = base_shop_stock;
                s.stocks.Add(st);
            }
            
            comp.shops.Add(s);
            return s;
        }
        public void addToShop(company comp, string cur, double volume, double unit_price)
        {
            foreach (shop s in comp.shops)
            {
                if (s.currency == cur)
                {
                    shop_stock ss = new shop_stock();
                    ss.date = DateTime.Now;
                    ss.employee = null;
                    ss.production_cost = 0;
                    ss.unit_price = unit_price;
                    ss.volume_in = volume;
                    ss.volume_out = 0;
                    s.stocks.Add(ss);

                    useStock(comp, volume);

                    return;
                }
            }
            shop new_s = new shop();
            new_s.currency = cur;
            comp.shops.Add(new_s);
            addToShop(comp, cur, volume, unit_price);
        }
        public void removeFromShop(company comp, string cur)
        {
            foreach (shop s in comp.shops)
            {
                if (s.currency == cur)
                {
                    double volume = 0;

                    var q =
                        from shop_stock ss in s.stocks
                        where ss.volume_out < ss.volume_in
                        orderby ss.date ascending
                        select ss;

                    foreach (shop_stock ss in q)
                    {
                        if (ss.volume_out > 0)
                        {
                            volume += ss.volume_in - ss.volume_out;
                            ss.volume_in = ss.volume_out;
                        }
                        else
                        {
                            volume += ss.volume_in;
                            s.stocks.Remove(ss);
                        }
                    }
                    if (volume > 0)
                    {
                        var q2 =
                            from stock st in comp.company_stock
                            where st.volume_out>0
                            orderby st.date descending
                            select st;

                        foreach (stock st in q2)
                        {
                            if (st.volume_out > volume)
                            {
                                st.volume_out -= volume;
                                break;
                            }
                            else
                            {
                                volume -= st.volume_out; 
                                st.volume_out = 0;
                            }
                        }
                    }
                }
            }
        }
        public double getShopValue(company comp, string cur)
        {
            double val = 0;
            foreach (shop s in comp.shops)
            {
                if (s.currency == cur)
                {
                    val += getShopValue(s);
                }
            }
            return val;
        }
        public shop getShop(company c, string cur)
        {
            foreach (shop s in c.shops)
            {
                if (s.currency == cur)
                    return s;
            }
            return null;
        }
        public double getShopValue(shop s)
        {
            double val = 0;
            foreach (shop_stock ss in s.stocks)
            {
                val += (ss.volume_in - ss.volume_out) * ss.unit_price;
            }
            return val;
        }
        public double getShopPrice(shop s)
        {
            var q =
                from shop_stock ss in s.stocks
                orderby ss.date descending
                select ss.unit_price;

            if (q.Count<double>() == 0)
                return 0;
            return q.First<double>();
        }
        public double getShopPrice(company c, string cur)
        {
            foreach (shop s in c.shops)
            {
                if (s.currency == cur)
                    return getShopPrice(s);
            }
            return 0;
        }
        public double getShopPrice(company c)
        {
            return getShopPrice(c, getAccount(c, Guid.Parse(c.default_account)).currency);
        }
        public double getShopStock(company comp, string cur)
        {
            double count = 0;
            foreach (shop s in comp.shops)
            {
                if (s.currency == cur)
                {
                    foreach (shop_stock ss in s.stocks)
                    {
                        count += ss.volume_in - ss.volume_out;
                    }
                }
            }
            return count;
        }
        public void sellShop(company comp, string cur, double volume)
        {
            foreach (shop s in comp.shops)
            {
                double vol = volume;
                double amount = 0;
                if (s.currency == cur)
                {
                    var q =
                        from shop_stock ss in s.stocks
                        where ss.volume_out < ss.volume_in
                        orderby ss.date ascending
                        select ss;

                    foreach (shop_stock ss in q)
                    {
                        if (ss.volume_in - ss.volume_out >= vol)
                        {
                            ss.volume_out = ss.volume_out + vol;
                            amount += vol * ss.unit_price;
                            vol = 0;
                            break;
                        }
                        else
                        {
                            amount += (ss.volume_in - ss.volume_out) * ss.unit_price;
                            vol -= ss.volume_in - ss.volume_out;
                            ss.volume_out = ss.volume_in;
                        }
                    }
                    transaction t = new transaction();
                    t.Date = DateTime.Now;
                    t.id = Guid.NewGuid().ToString();
                    t.Type = transaction_type.Sell;
                    t.Value = amount;
                    t.info = null;
                    t.Volume = volume - vol;
                    addTransaction(comp, cur, t);
                }
            }
        }
        #endregion

        #region Currency Management
        public double currencyToGOLD(currency_list cl, string fromCurrency, double val)
        {
            if (fromCurrency == "GLD")
                return val;

            foreach (currency c in cl.currencies)
            {
                if (c.short_name == fromCurrency)
                {
                    var q =
                        from currency_value cv in c.values_list
                        orderby cv.date descending
                        select cv;

                    currency_value q_cv = q.First<currency_value>();
                    return val * q_cv.value;
                }
            }
            return double.NaN;
        }

        public delegate void updateCaller(string short_currency);

        public void refreshCurrencies(ref currency_list cl, updateCaller updCaller)
        {
            DateTime dt = DateTime.Now;
            eApi.api api = new eApi.api();
            foreach (string scur in m_currency_code_list)
            {
                if (scur != "GLD")
                {
                    if (updCaller != null)
                        updCaller(scur);
                    System.Console.WriteLine("Loading " + scur);
                    currency c = getCurrency(cl, scur);
                    double last_rate = -1;
                    if (c == null)
                    {
                        c = new currency();
                        c.short_name = scur;
                        cl.currencies.Add(c);
                    }
                    else
                        last_rate = getLastCurrencyValue(c).value;

                    double current_rate = 0;
                    current_rate = api.currency_getRate(scur, "GOLD");

                    if (last_rate != current_rate)
                    {
                        currency_value cv = new currency_value();
                        cv.date = dt;
                        cv.value = current_rate;
                        c.values_list.Add(cv);
                        System.Console.WriteLine("    " + cv.value.ToString());
                    }
                    else
                        System.Console.WriteLine("    No Change");
                }
                else
                {
                    currency c = getCurrency(cl, scur);
                    if (c == null)
                    {
                        c = new currency();
                        c.short_name = scur;
                        cl.currencies.Add(c);
                        currency_value cv = new currency_value();
                        cv.date = dt;
                        cv.value = 1;
                        c.values_list.Add(cv);
                    }
                }
            }
        }

        public currency getCurrency(currency_list cl, string sName)
        {
            foreach (currency c in cl.currencies)
            {
                if (c.short_name == sName)
                    return c;
            }
            return null;
        }

        public currency_value getLastCurrencyValue(currency c)
        {
            var q =
                from currency_value cv in c.values_list
                orderby cv.date descending
                select cv;

            return q.First<currency_value>();
        }

        #endregion

        #region Charting
        public List<ChartItem> getOrganisationChartValue(organisation o, currency_list cl)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur = dt_cur.AddDays(1))
            {
                double gld_val = 0;
                foreach (account acc in o.account_list)
                {
                    double acc_val = 0;
                    acc_val += getAccountValue(acc, dt_cur);
                    if (acc.currency != "GLD")
                        gld_val += currencyToGOLD(cl, acc.currency, acc_val);
                    else
                        gld_val += acc_val;
                }

                foreach (company c in o.company_list)
                {
                    foreach (account acc in c.account_list)
                    {
                        double acc_val = 0;
                        acc_val += getAccountValue(acc, dt_cur);
                        if (acc.currency != "GLD")
                            gld_val += currencyToGOLD(cl, acc.currency, acc_val);
                        else
                            gld_val += acc_val;
                    }
                }

                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = gld_val;
                lst.Add(item);
            }

            return lst;
        }
        public List<ChartItem> getCompanyAccountChartValue(company c, currency_list cl)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur=dt_cur.AddDays(1))
            {
                double gld_val = 0;
                foreach (account acc in c.account_list)
                {
                    double acc_val = 0;
                    acc_val += getAccountValue(acc, dt_cur);
                    if (acc.currency != "GLD")
                        gld_val += currencyToGOLD(cl, acc.currency, acc_val);
                    else
                        gld_val += acc_val;
                }
                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = gld_val;
                lst.Add(item);
            }
            
            return lst;
        }
        public List<ChartItem> getOrganisationAccountChartValue(organisation o, currency_list cl)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur = dt_cur.AddDays(1))
            {
                double gld_val = 0;
                foreach (account acc in o.account_list)
                {
                    double acc_val = 0;
                    acc_val += getAccountValue(acc, dt_cur);
                    if (acc.currency != "GLD")
                        gld_val += currencyToGOLD(cl, acc.currency, acc_val);
                    else
                        gld_val += acc_val;
                }
                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = gld_val;
                lst.Add(item);
            }

            return lst;
        }
        public List<ChartItem> getAccountChartValue(account acc, currency_list cl)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur = dt_cur.AddDays(1))
            {
                double gld_val = 0;
                double acc_val = 0;
                acc_val += getAccountValue(acc, dt_cur);
                if (acc.currency != "GLD")
                    gld_val += currencyToGOLD(cl, acc.currency, acc_val);
                else
                    gld_val += acc_val;

                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = gld_val;
                lst.Add(item);
            }

            return lst;
        }
        public List<ChartItem> getEmployeeProductivityChartValue(company c, employee e)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur = dt_cur.AddDays(1))
            {
                double productivity = 0;

                productivity = getEmployeeProductivity(c, e, dt_cur);
                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = productivity;
                lst.Add(item);
            }

            return lst;
        }
        public List<ChartItem> getEmployeeProductChartValue(company c, employee e)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur = dt_cur.AddDays(1))
            {
                double product = 0;

                product = getEmployeeProduct(c, e, dt_cur);
                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = product;
                lst.Add(item);
            }

            return lst;
        }
        public List<ChartItem> getShopSellChartValue(company c, shop s)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            account acc = getAccount(c, s.currency);
            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur = dt_cur.AddDays(1))
            {
                double vol = getAccountSellValue(acc, dt_cur, dt_cur);
                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = vol;
                lst.Add(item);
            }

            return lst;
        }
        public List<ChartItem> getShopSellVolumeChartValue(company c, shop s)
        {
            List<ChartItem> lst = new List<ChartItem>();
            DateTime dt_fin = DateTime.Now.Date;
            DateTime dt_deb = dt_fin.AddMonths(-1);

            account acc = getAccount(c, s.currency);
            for (DateTime dt_cur = dt_deb; dt_cur <= dt_fin; dt_cur = dt_cur.AddDays(1))
            {
                double vol = getAccountSellVolumeValue(acc, dt_cur, dt_cur);
                ChartItem item = new ChartItem();
                item.date = dt_cur;
                item.volume = vol;
                lst.Add(item);
            }

            return lst;
        }
        #endregion
    }
    public class ChartItem
    {
        public DateTime date { get; set; }

        /*public double open { get; set; }
        public double high { get; set; }
        public double low { get; set; }
        public double close { get; set; }*/

        public double volume { get; set; }
    }
}
